﻿/* ----------------------------------------------------------------------------
 * Copyright (c) Philip Stears 
 *
 * This source code is subject to terms and conditions of the Microsoft Public 
 * License (Ms-PL).
 * 
 * By using this source code in any fashion, you are agreeing to be bound 
 * by the terms of the Microsoft Public License.
 * 
 * To request a copy of the Microsoft Public License, send a request by email
 * to license@connectbasic.net.
 *
 * This notice must not be removed from this software.
 * ---------------------------------------------------------------------------- */

namespace ConnectBasic.Shell.Implementation
{
    using System;
    using System.Diagnostics;
    using System.IO;
    using ConnectBasic.Shell.Extensibility;
    using ConnectBasic.Shell.Hosting;
    using ConnectBasic.Shell.Implementation.DefaultProjectInternals;
using ConnectDebug;

    /// <summary>
    /// Provides the default implementation of the 
    /// <see cref="IProject" /> interface.
    /// </summary>
    internal class DefaultProject : IProject
    {
        private IShell mShell;
        private IProjectStore mStore;
        private DefaultProjectItemCollection mItems;

        #region .ctor 

        internal DefaultProject(IShell shell, IProjectStore store)
        {
            Debug.Assert(shell != null);
            Debug.Assert(store != null);

            mShell = shell;
            mStore = store;

            // Load existing items
            mItems = new DefaultProjectItemCollection(this);
            LoadItems(store.Items);
        }

        private void LoadItems(IProjectStoreItemCollection items)
        {

            // Load each item
            foreach (var storeItem in mStore.Items)
            {

                // Resolve the type definition
                var typeName = Path.GetExtension(storeItem.Name);
                var def = ResolveType(typeName);

                if (def == null)
                {
                    throw new ArgumentOutOfRangeException("typeName");
                }

                // Load the item
                var item = def.LoadItem(this, storeItem);
            }
        }

        #endregion

        #region IProject Members

        public string DisplayName
        {
            get
            {
                return mStore.Properties.GetPropertyText("DisplayName");
            }
            set
            {
                mStore.Properties.SetPropertyText("DisplayName", value);
            }
        }

        public IProjectItemCollection Items
        {
            get { return mItems; }
        }

        public IShell Shell
        {
            get { return mShell; }
        }

        #endregion

        #region Internal Members

        internal IProjectItem AddItemInternal(string name, string typeName)
        {
            // Resolve the type definition
            var def = ResolveType(typeName);

            if (def == null)
            {
                throw new ArgumentOutOfRangeException("typeName");
            }

            // Create the backing store for the item
            var itemStore = mStore.Items.Add(name + typeName);

            // Create the item
            var item = def.CreateItem(this, itemStore);

            // Return it to the item collection
            return item;
        }

        #endregion

        #region Helpers

        private static readonly ItemTypeDef ItemTypeDefStandardModule = new ItemTypeDef(
            "ConnectBasic.Shell.Implementation.DefaultProjectInternals.StdModule.png",
            (def, project, storeItem) => new StandardModuleItem(def, project, storeItem),
            (def, project, storeItem) => new StandardModuleItem(def, project, storeItem)
            );

        private static ItemTypeDef ResolveType(string typeName)
        {

            // Only support standard modules currently
            if (".standardModule".Equals(typeName, StringComparison.OrdinalIgnoreCase))
            {
                return ItemTypeDefStandardModule;
            }

            return null;
        }

        #endregion

    }
}
